package colakao;
import java.util.*;

public class Player extends Thread
{
    protected ArrayList <Card> tPlayer;
    protected int QueueStop,Y_height,X_width;
    protected boolean active,stop;
    public Player()
    {
        active=false;
        tPlayer = new ArrayList<Card>();
        QueueStop = 0;
    }
    /** Adding specified card to the player.*/
    public void addCard(Card c)
    {   tPlayer.add(c); }
    /** Getting specified card fromt the player.*/
    public Card getCard(int index)
    {   return tPlayer.get(index);  }
    /** Throwing specified card(s) from Arraylist Selected in DrawTable. Updating punish/demands if needed.*/
    public void throwCard(DrawTable table)
    {
        if(table.BackUpDemand!='0')
        {
            table.dealer.demand=table.BackUpDemand;
            if(table.BackUpDemandQueue!=0)
                table.dealer.demandQueue=table.BackUpDemandQueue;
            table.BackUpDemand='0';
            table.BackUpDemandQueue=0;
        }
        for(int i=0; i<table.Selected.size(); i++)
        {
            if(table.dealer.getActiveCard().joker==false)    /** recycling nie uzywanych kart*/
                table.dealer.CardsUsed.add(new Card(table.dealer.getActiveCard()));
            else
                table.dealer.CardsUsed.add(new Card('B','\0',0,Card.ImagePath('\0', 'B',table.taliaI),true));
            table.dealer.ActiveCard = new Card(tPlayer.get(table.Selected.get(i).ind));
            if(table.dealer.ActiveCard.punish!=6 && table.dealer.ActiveCard.punish!=7)
                table.dealer.get+=table.dealer.ActiveCard.punish;
        }
        if(table.dealer.get<0)   /** przypadek, gdy lezy karta o figurze 4 */
        {
            setStop(table.dealer);
            int stop=MouseAdapters.getNext(table);
            punishStop(table.players[stop],table.dealer);
        }
        /** obsluga zadan koloru/figury*/
        if(table.dealer.demandQueue>0 && table.Selected.get(table.Selected.size()-1).rank!='J')
            table.dealer.demandQueue--;
        if(table.dealer.demand!='0' && table.dealer.demandQueue==0 && table.dealer.getActiveCard().rank!='A')
            table.dealer.demand='0';
        if(table.dealer.demand!='H' && table.dealer.demand!='D' && table.dealer.demand!='S' &&
           table.dealer.demand!='C' && table.dealer.demandQueue==0)
            table.dealer.demand='0';
        for(int i=0; i<table.Selected.size(); i++)
        {
            for(int j=0; j<table.Selected.size()-1; j++)
            {
                if(table.Selected.get(j).ind<table.Selected.get(j+1).ind)
                {
                    Card swap = new Card(table.Selected.get(j));
                    table.Selected.set(j, table.Selected.get(j+1));
                    table.Selected.set(j+1,swap);
                }
            }
        }
        for(int i=0; i<table.Selected.size(); i++)  /** usuwanie kart, ktore gracz wyrzucil*/
            tPlayer.remove(table.Selected.get(i).ind);
        table.Selected.clear();                     /** czyszczenie ArrayListy z wybranymi przez gracza kartami*/
        PunishDec(table);                           /** obnizanie kary czekania, jesli faktycznie wystepuje*/
	if(table.players[0].tPlayer.isEmpty() || table.players[1].tPlayer.isEmpty())
            table.koniec_gry=true;
        NetworkAdapters.Write(table);               /** wysylanie kart protkolem sieciowym */
    }
    /** Method returning wheter the move is possible with the card from the specified index.*/
    public boolean movePossible(int index, Dealer dealer)
    {
        if(stop==true)  /** jezeli gracz czeka, nie ma mozliwosci ruchu*/
            return false;
        else if(tPlayer.get(index).rank=='B')   /** poza czekaniem, gracz majac jokera ma zawsze mozliwosc ruchu*/
            return true;
        else if ( QueueStop!=0 && tPlayer.get(index).rank!='4')
            return false;
        else if ( dealer.ActiveCard.rank=='K' && dealer.get!=0 && (dealer.ActiveCard.color=='H' || dealer.ActiveCard.color=='S' ))
            return battleOfKing(dealer.ActiveCard, index);
        else if ( (dealer.ActiveCard.rank=='2' || dealer.ActiveCard.rank=='3' ) && dealer.get!=0)
            return battleOf23(dealer.ActiveCard, index);
        else if( dealer.demand!='0')
            return battleOfDemand(index, dealer);
        else if (dealer.ActiveCard.rank=='4')
            return battleOfStop(index,dealer);
        else if( dealer.ActiveCard.rank==tPlayer.get(index).rank || dealer.ActiveCard.color==tPlayer.get(index).color)
            return true;
        return false;
    }
    /** Game rule (when King of Hearts/Spades is an ActiveCard).*/
    private boolean battleOfKing(Card ActiveCard, int index)
    {
        if (ActiveCard.color=='H' && tPlayer.get(index).color=='H' && (tPlayer.get(index).rank=='2' || tPlayer.get(index).rank=='3')) 
            return true;
        else if (ActiveCard.color=='S' && tPlayer.get(index).color=='S' && (tPlayer.get(index).rank=='2' || tPlayer.get(index).rank=='3')) 
            return true;
        else if ((tPlayer.get(index).color=='H' || tPlayer.get(index).color=='S') && tPlayer.get(index).rank=='K') 
            return true;
        return false;
    }
    /** Game rule (when 2 or 3 is an ActiveCard).*/
    private boolean battleOf23(Card ActiveCard, int index)
    {
        if (ActiveCard.color==tPlayer.get(index).color && (tPlayer.get(index).rank=='2' || tPlayer.get(index).rank=='3')) 
            return true;
        else if((ActiveCard.color=='H' || ActiveCard.color=='S') && tPlayer.get(index).rank=='K' && tPlayer.get(index).color==ActiveCard.color)
            return true;
        else if (ActiveCard.color!=tPlayer.get(index).color && ActiveCard.rank==tPlayer.get(index).rank) 
            return true;
        return false;
    }
    /** Game rule (when 4 is an ActiveCard).*/
    private boolean battleOfStop(int index, Dealer dealer)
    {
        if(tPlayer.get(index).rank=='4')
            return true;
        else if(QueueStop==0 && (tPlayer.get(index).rank==dealer.ActiveCard.rank || tPlayer.get(index).color==dealer.ActiveCard.color))
            return true;
        return false;
    }
    /** Game rule (when demandining figure or rank).*/
    private boolean battleOfDemand(int index, Dealer dealer)
    {
        if(dealer.demand=='K' && (tPlayer.get(index).color=='S' || tPlayer.get(index).color=='H'))
            return false;
        else if(tPlayer.get(index).rank==dealer.demand || tPlayer.get(index).color==dealer.demand)
            return true;
        else if( tPlayer.get(index).rank=='A' && dealer.getActiveCard().rank=='A')
            return true;
        else if( tPlayer.get(index).rank=='J' && dealer.getActiveCard().rank=='J')
            return true;
        else if( tPlayer.get(index).rank=='J' && dealer.demandQueue!=0 && (dealer.getActiveCard().color==tPlayer.get(index).color || dealer.getActiveCard().rank=='J'))
            return true;
        return false;
    }
    /** When player get a card he can peek it.*/
    public void peekCard(int punish, DrawTable table)
    {
        if(table.dealer.CardDeck.size()<punish && table.dealer.CardsUsed.size()>0)    /** jesli brak kart do pobrania wykorzystywany jest zbior used*/
        {
            for(int i=table.dealer.CardsUsed.size()-1; i>=0; i--)
                table.dealer.CardDeck.add(new Card(table.dealer.CardsUsed.get(i)));
            table.dealer.CardsUsed.clear();
            Collections.shuffle(table.dealer.CardDeck);
        }
        if(table.dealer.CardDeck.size()>0)
        {
            if(PunishDec(table));
            else
            {
                tPlayer.add( table.dealer.CardDeck.get(table.dealer.CardDeck.size()-1));
                if(table.dealer.demandQueue>0)
                    table.dealer.demandQueue--;
                if(table.dealer.demand!='H' && table.dealer.demand!='D' && table.dealer.demand!='S' && table.dealer.demand!='C' && table.dealer.demandQueue==0)
                    table.dealer.demand='0';
                table.dealer.CardDeck.remove(table.dealer.CardDeck.size()-1);
                table.peekFrame(this,punish-1,table.players[0].active);
            }
        }
    }
    /** Method to get more cards, no peeking.*/
    protected void getCards(Dealer dealer, int punish)
    {
        int a = dealer.DeckSize()-1;
        for(int i=0; i<punish; i++,a--)
            tPlayer.add(dealer.getCard(a));
        dealer.RemoveSubList(a, dealer.DeckSize()-1);
        dealer.get=0;
    }
    /** Method to determine how much the waiting queue is.*/
    public void setStop(Dealer dealer)
    {
        dealer.stopQueue=Math.abs(dealer.get)*dealer.players;
    }
    public void punishStop(Player player, Dealer dealer)
    {
        if(player.QueueStop==0 && dealer.stopQueue>0)
        {
            player.QueueStop=dealer.stopQueue+QueueStop;
            dealer.stopQueue=0;
            QueueStop=0;
            dealer.get=0;
        }
        else if(QueueStop!=0 && dealer.stopQueue>0)
        {
            player.QueueStop=QueueStop+dealer.stopQueue;
            QueueStop=0;
            dealer.stopQueue=0;
            dealer.get=0;
        }
    }
    /** Method to change Joker to specified card.*/
    public void transformJoker(int index, char c, char r, int p, String path)
    {
        tPlayer.get(index).color = c;
        tPlayer.get(index).rank = r;
        tPlayer.get(index).punish = p;
        tPlayer.get(index).pathAwers = path;
    }
    public void setCard(Card card, int index)
    {
        tPlayer.get(index).color = card.color;
        tPlayer.get(index).rank = card.rank;
        tPlayer.get(index).punish = card.punish;
        tPlayer.get(index).pathAwers = card.pathAwers;
        tPlayer.get(index).ind = card.ind;
    }
    public int getPlayerCardsAmount()
    {
        return tPlayer.size();
    }
    /** Method which cheks if one of the players suffers punish of stop.*/
    protected boolean PunishDec(DrawTable table)    
    {
        boolean warunek=false;
        if( (table.players[0].QueueStop>0 && table.Server==true) || (table.players[1].QueueStop>0 && table.Server==false) )
        {
            warunek=true;
            if(table.players[0].QueueStop>0 && table.Server==true)
            {
                table.players[0].stop=true;
                table.players[1].stop=false;
                table.players[0].QueueStop--;
                if(table.players[0].QueueStop==0)
                    table.players[0].stop=false;
            }
            if(table.players[1].QueueStop>0 && table.Server==false)
            {
                table.players[0].stop=false;
                table.players[1].stop=true;
                table.players[1].QueueStop--;
                if(table.players[1].QueueStop==0)
                    table.players[1].stop=false;
            }
            table.reDrawComponents(true,0);
            MouseAdapters.blockContent(table,1);
            NetworkAdapters.Write(table);
        }
        return warunek;
    }
}